
Spring中包含了以上模块,主要用到了以下几种设计模式
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
# 一、基础信息
# bean的定义
- Bean是一个被
实例化、组装、并被Spring容器所管理的对象,是由容器提供的配置元数据(如bean.xml)创建的。(下图是Bean与Spring容器的关系)

# bean的三种元数据配置(bean的创建)
- 基于XML的配置
<beans>
<bean name="" class=""></bean>
</beans>
2
3
- 基于注解的配置
@Component
public class MyBeanConfig {
@Autowired
private Country country;
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 基于Java的配置(
@Configuration实现自动依赖注入,且通过代理操作,而@Component则没有代理,且需要加上@Autowired,否则两个方法返回的是不同的实例)
@Configuration
public class MyBeanConfig {
@Bean
public Country country(){
return new Country();
}
@Bean
public UserInfo userInfo(){
return new UserInfo(country());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# bean的作用域
(可通过Xml的scope属性及@Scope注解进行配置)
- singleton
- prototype
- request
- session
- global-session
# 二、生命周期
Bean的生命周期看起来很复杂,其核心过程主要包括:
- Bean元信息加载
- Bean实例化
- Bean属性填充
- Bean初始化
- Bena的使用
- Bean的销毁
除了上述的核心流程外,Spring还提供了多个钩子,可以辅助对其周期数据进行修改和获取,主要有以下几个:
- Aware获取BeanName、ApplicationContext,BeanFactory
- @PostContract、init-method初始化
- @PreDestory销毁前的资源关闭

1、Spring对Bean进行
实例化(相当于程序中的new Xx(),反射实现)2、Spring将值和Bean的
引用注入进Bean对应的属性中(反射实现)3、如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给
setBeanName()方法(实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)4、如果Bean实现了BeanFactoryAware接口,Spring将
调用setBeanFactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)5、如果Bean实现了ApplicationContextAwaer接口,Spring容器将
调用setApplicationContext(ApplicationContext ctx)方法,把应用上下文作为参数传入.(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )6、如果Bean实现了BeanPostProcess接口,Spring将调用它们的
postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)7、如果Bean实现了InitializingBean接口,Spring将调用它们的
afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。8、如果Bean实现了BeanPostProcess接口,Spring将调用它们的
postProcessAfterInitialization(后初始化)方法(作用与第六步的一样,只不过是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )9、经过以上的工作后,Bean将
一直驻留在应用上下文中给应用使用,直到应用上下文被销毁10、如果Bean实现了DispostbleBean接口,Spring将调用它的
destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。
综合上面十个步骤,可以简化为:Bean实例的创建、Bean属性的注入、Bean相关Aware接口的实现,Bean实例调用前的初始化、Bean实例的调用、Bean实例销毁前的初始化、Bean实例的销毁
# 三、循环依赖处理
如何解决循环依赖问题?
Spring采用三级缓存解决循环依赖问题,缓存本质上就是为了提前暴露Bean(半成品),避免循环依赖导致的死循环问题。
名称 描述 singletonObjects 一级缓存,存放完整的 Bean。 earlySingletonObjects 二级缓存,存放提前暴露的Bean,Bean 是不完整的,未完成属性注入和执行 init 方法。 singletonFactories 三级缓存,存放的是 Bean 工厂,主要是生产 Bean,存放到二级缓存中。 A、B循环依赖的处理过程:
- 实例化 A,此时 A 还未完成属性填充和初始化方法(@PostConstruct)的执行,A 只是一个半成品。
- 为 A 创建一个 Bean 工厂,并放入到 singletonFactories 中。
- 发现 A 需要注入 B 对象,但是一级、二级、三级缓存均为发现对象 B。
- 实例化 B,此时 B 还未完成属性填充和初始化方法(@PostConstruct)的执行,B 只是一个半成品。
- 为 B 创建一个 Bean 工厂,并放入到 singletonFactories 中。
- 发现 B 需要注入 A 对象,此时在一级、二级未发现对象 A,但是在三级缓存中发现了对象 A,从三级缓存中得到对象 A,并将对象 A 放入二级缓存中,同时删除三级缓存中的对象 A。(注意,此时的 A 还是一个半成品,并没有完成属性填充和执行初始化方法)
- 将对象 A 注入到对象 B 中。
- 对象 B 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 B。(此时对象 B 已经是一个成品)
- 对象 A 得到对象 B,将对象 B 注入到对象 A 中。(对象 A 得到的是一个完整的对象 B)
- 对象 A 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 A。
为什么需要三级缓存?
Spring的三级缓存存放的是创建Bean的工厂实例(该实例可以提前创建代理对象),是为了解决AOP代理问题,通常的情况下,Spring Bean在完成初始化后开始为其创建代理对象,而在循环依赖过程中,依赖的对象并没有完成实例化,如果直接注入,那么注入的是普通Bean而非代理Bean,所以第三级缓存就是为了提前创建及暴露代理对象。
(当然,如果将代理对象的创建过程提前,则可以不需要第三级缓存,直接将创建的代理对象半成品放入二级缓存即可)
← Spring AOP Spring IOC →